module MediaTools
  
  class Time
    include Comparable
      
    MAX_MINUTES = 1 << 16
    MAX_SECONDS = 60
    MAX_FRAMES = 75
      
    attr_reader :minutes, :seconds, :frames
      
    def initialize(minutes = 0, seconds = 0, frames = 0)
      self.minutes = minutes
      self.seconds = seconds
      self.frames = frames
    end
      
    def Time._limited_setter(name, upper_value)
      define_method("#{name}=") do |value|
        raise ArgumentError.new("invalud #{name} value") if !((0..upper_value - 1) === value)
        instance_variable_set "@#{name}", value
      end
    end
      
    def to_frames
      @frames + MAX_FRAMES * @seconds + @minutes * MAX_SECONDS * MAX_FRAMES
    end
      
    def from_frames(value)
      @frames = value % 75
      @seconds = (value.div MAX_FRAMES) % MAX_SECONDS
      @minutes = value.div MAX_FRAMES * MAX_SECONDS
      self
    end
      
    def <=>(another)
      return to_frames <=> another.to_frames
    end
      
    def from_s(str)
      raise ArgumentError.new("given string is not a time representation: #{str}") unless str =~ /(\d\d):(\d\d):(\d\d)/
      self.minutes = $1.to_i
      self.seconds = $2.to_i
      self.frames = $3.to_i
      self
    end
      
    def to_s
      "#{minutes}:#{seconds}:#{frames}"
    end
      
    def +(another)
      Time.new.from_frames(self.to_frames + another.to_frames)
    end
      
    def -(another)
      Time.new.from_frames(self.to_frames - another.to_frames)        
    end

    _limited_setter :minutes, MAX_MINUTES
    _limited_setter :seconds, MAX_SECONDS
    _limited_setter :frames, MAX_FRAMES
  end
  
  
end